/**
 * 用户资金操作
 */
// 涉及的表名
const dbName = require("../config.js");

var dao = {};
var util = {};
// 初始化
dao.init = function(obj) {
	util = obj;
}
const accountNameObj = {
	"account_balance": "钱包",
	"account_integral": "积分",
	"account_reward": "提现"
};


/**
 * 修改用户余额（使用事务）
 * 调用示例
await vk.daoCenter.moneyDao.updateAccountBalanceForTransaction({
	db: transaction,
	user_id: uid,
	value: value, // 此值始终为正整数 100=1元
	isAdd: false, // true 增加 false 减少
	no: no,
	title: title,
	comment: comment,
	add_type: 3, // 1 人工录入 2 用户线上充值 3 消费 4 退款 5 转账 6 余额转换 7 奖励发放 8 解锁 9 提现 10 提现拒绝后返还
	updateTotal: true,
});
 */
dao.updateAccountBalanceForTransaction = async (data) => {
	let { vk, _ } = util;
	let res = { code: 0, msg: "" };
	// 数据库操作开始-----------------------------------------------------------
	let {
		db,
		user_id,
		no,
		title,
		comment,
		add_type,
		isAdd,
		create_uid
	} = data;
	let accountInfo = {
		balanceName: "余额",
		accountKey: "account_balance",
		balanceKey: "balance",
		usedBalanceKey: "used"
	};

	res = await dao.updateAccountPubFn({
		...data,
		...accountInfo,
	});
	if (res.code !== 0 || !res.updateValue) {
		return res;
	}
	// 增加收支记录 开始-----------------------------------------------------------
	res.id = await vk.baseDao.add({
		db,
		dbName: dbName.balanceRec,
		dataJson: {
			user_id,
			value: res.updateValue,
			balance: res.balance,
			account: res.account,
			no,
			type: isAdd ? 1 : 2,
			title,
			comment,
			add_type,
			create_uid: create_uid ? create_uid : user_id
		}
	});
	// 增加收支记录 结束-----------------------------------------------------------
	// 数据库操作结束-----------------------------------------------------------
	return res;
};


/**
 * 修改用户积分（使用事务）
 * 调用示例
await vk.daoCenter.moneyDao.updateAccountIntegralForTransaction({
	db: transaction,
	user_id: uid,
	value: value, // 此值始终为正整数 100=1元
	isAdd: false, // true 增加 false 减少
	no: no,
	title: title,
	comment: comment,
	add_type: 3, // 1 人工录入 2 用户线上充值 3 消费 4 退款 5 转账 6 余额转换 7 奖励发放 8 解锁 9 提现 10 提现拒绝后返还
	updateTotal: true,
});
 */
dao.updateAccountIntegralForTransaction = async (data) => {
	let { vk, _ } = util;
	let res = { code: 0, msg: "" };
	// 数据库操作开始-----------------------------------------------------------
	let {
		db,
		user_id,
		no,
		title,
		comment,
		add_type,
		isAdd,
		create_uid
	} = data;
	let accountInfo = {
		balanceName: "积分",
		accountKey: "account_integral",
		balanceKey: "balance",
		usedBalanceKey: "used"
	};

	res = await dao.updateAccountPubFn({
		...data,
		...accountInfo,
	});
	if (res.code !== 0 || !res.updateValue) {
		return res;
	}
	// 增加收支记录 开始-----------------------------------------------------------
	res.id = await vk.baseDao.add({
		db,
		dbName: dbName.integralRec,
		dataJson: {
			user_id,
			value: res.updateValue,
			balance: res.balance,
			account: res.account,
			no,
			type: isAdd ? 1 : 2,
			title,
			comment,
			add_type,
			create_uid: create_uid ? create_uid : user_id
		}
	});
	// 增加收支记录 结束-----------------------------------------------------------
	// 数据库操作结束-----------------------------------------------------------
	return res;
};


/**
 * 修改用户可提现余额 (使用事务)
 * 调用示例
await vk.daoCenter.moneyDao.updateAccountRewardForTransaction({
	db: transaction,
	user_id: uid,
	value: value,
	isAdd: false,
	updateTotal: true,
	no: no,
	title: ``,
	comment: ``,
	add_type: 7, // 1 人工录入 2 用户线上充值 3 消费 4 退款 5 转账 6 余额转换 7 奖励发放 8 解锁 9 提现 10 提现拒绝后返还
	reward_type: 0, // 0: 未分类奖励 1:二级分销  2:区域奖励
});
 */
dao.updateAccountRewardForTransaction = async (data) => {
	let { vk, _ } = util;
	let res = { code: 0, msg: "" };
	// 数据库操作开始-----------------------------------------------------------
	let {
		db,
		user_id,
		no,
		title,
		comment,
		add_type,
		reward_type,
		isAdd,
		create_uid,

		user_id2,
		calc_rule,
	} = data;
	let accountInfo = {
		balanceName: "可提现余额",
		accountKey: "account_reward",
		balanceKey: "allow",
		usedBalanceKey: "used"
	};
	if ([9, 10].indexOf(add_type) > -1) {
		accountInfo.usedBalanceKeyName = "success";
	}

	res = await dao.updateAccountPubFn({
		...data,
		...accountInfo,
	});
	if (res.code !== 0 || !res.updateValue) {
		return res;
	}
	// 增加收支记录 开始-----------------------------------------------------------
	res.id = await vk.baseDao.add({
		db,
		dbName: dbName.rewardRec,
		dataJson: {
			user_id,
			value: res.updateValue,
			balance: res.balance,
			account: res.account,
			no,
			type: isAdd ? 1 : 2,
			title,
			comment,
			add_type,
			create_uid: create_uid ? create_uid : user_id,
			reward_type,
			user_id2,
			calc_rule,
		}
	});
	// 增加收支记录 结束-----------------------------------------------------------
	// 数据库操作结束-----------------------------------------------------------
	return res;
};

/**
 * 修改用户待提现余额(在途奖励) (使用事务)
 * 调用示例
await vk.daoCenter.moneyDao.updateAccountWaitRewardForTransaction({
	db: transaction,
	user_id: uid,
	value: value,
	isAdd: false,
	updateTotal: true,
	no: no,
	title: ``,
	comment: ``,
	add_type: 7, // 1 人工录入 2 用户线上充值 3 消费 4 退款 5 转账 6 余额转换 7 奖励发放 8 解锁 9 提现 10 提现拒绝后返还
	reward_type: 0, // 0: 未分类奖励 1:二级分销  2:区域奖励
	reward_type_lv, // 1 直推 2 间推
	calc_rule: usersRewardItem.calc_rule,
	goods_reward_list: usersRewardItem.goods_reward_list,
});
 */
dao.updateAccountWaitRewardForTransaction = async (data) => {
	let { vk, _ } = util;
	let res = { code: 0, msg: "" };
	// 数据库操作开始-----------------------------------------------------------
	let {
		db,
		user_id,
		no,
		title,
		comment,
		add_type,
		reward_type,
		reward_type_lv,
		isAdd,

		user_id2,
		is_freeze = true,
		unfreeze_time,
		calc_rule,
		goods_reward_list
	} = data;
	let accountInfo = {
		balanceName: "在途余额",
		accountKey: "account_reward",
		balanceKey: "wait"
	};

	if (!unfreeze_time && is_freeze) {
		// 如果没传 unfreeze_time 参数，则解冻时间默认为8天后
		let { todayStart } = vk.pubfn.getCommonTime(new Date());
		unfreeze_time = vk.pubfn.getOffsetTime(todayStart, {
			day: 8,
			mode: "after", // after 之后 before 之前
		});
	}

	res = await dao.updateAccountPubFn({
		...data,
		...accountInfo,
	});
	if (res.code !== 0 || !res.updateValue) {
		return res;
	}
	// 增加收支记录 开始-----------------------------------------------------------
	res.id = await vk.baseDao.add({
		db,
		dbName: dbName.rewardRec,
		dataJson: {
			user_id,
			value: res.updateValue,
			balance: res.balance,
			account: res.account,
			no,
			type: isAdd ? 1 : 2,
			title,
			comment,
			add_type,
			reward_type,
			reward_type_lv,
			user_id2,
			is_freeze,
			unfreeze_time,
			calc_rule,
			goods_reward_list,
		}
	});
	// 增加收支记录 结束-----------------------------------------------------------
	// 数据库操作结束-----------------------------------------------------------
	return res;
};


/**
 * 解锁奖励（减少待提现，增加可提现，无需增加收支记录）
 * 调用示例
await vk.daoCenter.moneyDao.unlockReward({
	db:transaction,
	user_id : uid
});
 */
dao.unlockReward = async (data) => {
	let { vk, _ } = util;
	let res = { code: 0, msg: "" };
	// 数据库操作开始-----------------------------------------------------------
	let {
		db,
		user_id
	} = data;
	let time = Date.now();
	// 获取总可解锁的记录数量
	let unlockRewardCount = await vk.daoCenter.userDao.countUnlockReward({
		user_id,
		time
	});
	if (unlockRewardCount <= 0) {
		return { code: 0, msg: "无需解锁" };
	}
	// 获取总可解锁金额
	let unlockRewardMoney = await vk.daoCenter.userDao.sumUnlockReward({
		user_id,
		time
	});
	// 将奖励记录解锁
	let updateNum = await vk.daoCenter.userDao.updateUnlockReward({
		user_id,
		time
	});
	if (updateNum <= 0) {
		return { code: 0, msg: "无需解锁" };
	}
	if (unlockRewardMoney > 0) {
		res.userInfo = await vk.daoCenter.userDao.updateAndReturn({
			db,
			whereJson: {
				_id: user_id,
				"account_reward.wait": _.gte(unlockRewardMoney)
			},
			dataJson: {
				"account_reward.wait": _.inc(unlockRewardMoney * -1),
				"account_reward.allow": _.inc(unlockRewardMoney),
			}
		});
	}
	res.unlockRewardMoney = unlockRewardMoney;
	// 数据库操作结束-----------------------------------------------------------
	return res;
};

/**
 * 修改账户资金公共函数
 * 示例
await dao.updateAccountPubFn({
	...data,
	balanceName,
	accountKey,
	balanceKey,
});
 */
dao.updateAccountPubFn = async (data) => {
	let { vk, _ } = util;
	let res = { code: 0, msg: "" };
	let {
		db, // 事务实例

		balanceName, // 余额名称
		accountKey, // 账户字段名
		balanceKey, // 操作的余额字段名
		usedBalanceKey = "used",

		value, // 变动的值
		isAdd, // true:添加 false:减少
		checkBalance = true, // 当isAdd为false时，是否需要检测余额是否足够减
		updateTotal, // 是否修改累计
		updateUsed, // 是否需要修改已使用
		user_id,
	} = data;

	// 参数非空检测
	let nullKey = vk.pubfn.isNullOneByObject({ user_id, value });
	if (nullKey) {
		res.code = -1;
		res.msg = '参数 ' + nullKey + ' 不能为空';
		throw new Error(JSON.stringify(res));
	}

	if (value == 0) {
		res.code = 0;
		res.msg = `${balanceName}必须大于0`;
		res.value = value; // 这里不抛异常是因为加0没有变化，故不需要有记录
		return res;
	}
	if (value < 0) {
		res.code = -1;
		res.msg = `${balanceName}必须大于0`;
		res.value = value;
		throw new Error(JSON.stringify(res)); // 小于0需要抛异常
	}
	let updateValue = isAdd ? value : value * -1;
	if (isAdd) checkBalance = false; // 如果是添加，则不需要检测余额是否足够
	if (typeof updateTotal === "undefined") {
		// 默认情况下，添加时需要同步添加累计，而减少时不减少累计。
		updateTotal = isAdd ? true : false;
	}
	if (typeof updateUsed === "undefined") {
		// 默认情况下，减少时需要同步添加已使用，而增加时不修改已使用
		// 如果已经修改了累计，则不修改已使用
		updateUsed = isAdd || updateTotal ? false : true;
	}
	let whereJson = {
		_id: user_id,
	};
	if (checkBalance) {
		// 如果需要检测余额是否足够，则带上条件 余额大于等于 value
		whereJson[`${accountKey}.${balanceKey}`] = _.gte(value);
	}
	let dataJson = {};

	dataJson[`${accountKey}.${balanceKey}`] = _.inc(updateValue); // 累加或累减

	if (updateTotal) {
		// 修改累计
		dataJson[`${accountKey}.total`] = _.inc(updateValue);
	}
	if (updateUsed) {
		// 修改已使用
		dataJson[`${accountKey}.${usedBalanceKey}`] = _.inc(updateValue * -1);
	}

	let newInfo = await vk.baseDao.updateAndReturn({
		db,
		dbName: dbName.user,
		whereJson,
		dataJson
	});

	if (checkBalance) {
		if (vk.pubfn.isNull(newInfo) || !newInfo[accountKey] || newInfo[accountKey][balanceKey] < 0) {
			res.code = -1;
			let accountName = accountNameObj[accountKey] || "";
			res.msg = `${accountName}余额不足!`;
			res.accountKey = accountKey;
			res.accountName = accountName;
			throw new Error(JSON.stringify(res));
		}
	}

	res.updateValue = updateValue; // 要修改的值
	res.balance = newInfo[accountKey][balanceKey]; // 修改后的余额数据
	res.account = newInfo[accountKey]; // 修改后的账户数据（包含了余额，累计等）

	let typeName = isAdd ? "增加" : "扣除";
	// 添加uniCloud控制台日志
	if (["积分"].indexOf(balanceName) > -1) {
		uniCloud.logger.log(`${user_id}（${newInfo.nickname}）:【${balanceName}】【${typeName}】${value} 剩余: ${res.balance}`);
	}else {
		uniCloud.logger.log(`${user_id}（${newInfo.nickname}）:【${balanceName}】【${typeName}】${value / 100} 剩余: ${res.balance / 100}`);
	}
	return res;
};

module.exports = dao;
